#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <string>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <arpa/inet.h>
#include <unistd.h>
#include "time.h"
#include "Base64.cpp"
#include "RSA1.cpp"
#define MYPORT 3490
#define BACKLOG 10
#define MAXDATASIZE 1000
using namespace std;
class Receiver{
public:
	Receiver();
	void run();
	void sendMsg(const string s);
	string receiveMsg();
	void get_negotiation();
private:
	int sockfd;
	int new_fd;
	int numbytes;
	clock_t start, finish;
	double duration;
	char buf[MAXDATASIZE];
	struct sockaddr_in my_addr;
	struct sockaddr_in their_addr;
	socklen_t sin_size;
	void initialize();
};
Receiver::Receiver(){
	this->initialize();
}
void Receiver::initialize(){
	if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1){
		perror("socket error");
		exit(1);
	}
	my_addr.sin_family=AF_INET;
	my_addr.sin_port=htons(MYPORT);
	my_addr.sin_addr.s_addr=INADDR_ANY;
	bzero(&(my_addr.sin_zero),sizeof(my_addr.sin_zero));
	if(bind(sockfd,(struct sockaddr *)&my_addr,sizeof(struct sockaddr))==-1){
		perror("bind error");
		exit(1);
	}
	if(listen(sockfd,BACKLOG)==-1){
		perror("listen error");
		exit(1);
	}
}
void  Receiver::sendMsg(const string s){
	if(!fork()){
		if(send(new_fd,s.c_str(),s.size(),0)==-1)
			perror("send error");
		close(new_fd);
		exit(0);
	}
}

string Receiver::receiveMsg(){
	char buf[MAXDATASIZE];
	if((numbytes=recv(new_fd,buf,MAXDATASIZE,0))==-1){
		perror("recv");
		exit(1);
	}
	buf[numbytes]='\0';
	string str(buf);
	return str;
}
void Receiver::run(){
	while(1){
		sin_size=sizeof(struct sockaddr_in);
		if((new_fd=accept(sockfd,(struct sockaddr *)&their_addr,&sin_size))==-1){
			perror("accept");
			continue;
		}
		//printf("Server:got connection from %s\n",inet_ntoa(their_addr.sin_addr));
		start=clock();
		string type=receiveMsg();
		if(type=="negotiation"){
			sendMsg("OK");
			get_negotiation();
		}
		while(waitpid(-1,NULL,WNOHANG)>0);
	}
}
void Receiver::get_negotiation(){
	string recvCode=receiveMsg();
	ifstream fin;
	fin.open("key.txt");
	int d1,n1;
	fin>>d1>>n1;
	string res=RSA_Decrypt(d1,n1,recvCode);
	char * dec_output = Base64Decode((char *)res.c_str(), res.size(), true);
	//close(new_fd);
	fin.close();
	string receiveStr=dec_output;
	cout<<receiveStr<<endl;
	string cipher;
	istringstream iss(receiveStr);
	iss>>cipher;
	iss>>cipher;
	//save the encrypt ciphers
	ofstream fout("Cipher1.txt");
	fout<<cipher;
	fout.close();
	finish=clock();
	int duration = finish - start;
	//response duration and status
	char dur[256];
	sprintf(dur,"%d",duration);
	string response="negatiation OK,duration:";
	string tmpStr=dur;
	response+=tmpStr+"m";
	cout<<response<<endl;
	sendMsg(response);
}
int main(int argc, char const *argv[])
{
	Receiver rec;
	rec.run();
	return 0;
}